﻿
using Autofac;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Redbus.Events;
using Redbus.Interfaces;
using SqlSugar;
using System.ComponentModel;
using Warehouse.Entites;
using Warehouse.Services.Repository;
using WCS.Entities;
using WCS.Entities.Api;
using WCS.IServices;

namespace WCS.Controllers

{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class JobController : ControllerBase
    {
        #region  Filed

        private readonly ILogger<JobController> logger;
        private readonly Repository<Job> jobRepoitory;
        private readonly Repository<Material> materialRepoitory;
        private readonly IEventBus eventBus;
        //private readonly IOptionsMonitor<SystemParameter> options;
        private readonly IDeviceManager deviceManager;
        #endregion

        public JobController(
            ILogger<JobController> logger,
            Repository<Job> jobRepoitory,
            Repository<Material> materialRepoitory,
            IEventBus eventBus,
            IDeviceManager deviceManager)
        {
            this.logger = logger;
            this.jobRepoitory = jobRepoitory;
            this.materialRepoitory = materialRepoitory;
            this.eventBus = eventBus;
            this.deviceManager = deviceManager;
            
        }


        #region 创建

        /// <summary>
        /// 创建任务
        /// </summary>
        /// <param name="job">新的任务</param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost]
        public async Task<ActionResult<ApiResult>> Create([FromBody] Job job)
        {
            try
            {
                //任务校验
                if (await jobRepoitory.IsExistAsync(j => j.Id == job.Id))
                    return ApiResultHelp.Error(400, "任务已存在");

                if (await jobRepoitory.IsExistAsync(j => j.Target == job.Target && j.Status < TaskState.Complete))
                    return ApiResultHelp.Error(400, "该目标点存在其它未完成的任务");

                if (!deviceManager.Ports.Any(p => p.Id == job.Target))
                    return ApiResultHelp.Error(400, "不存在该目标点");

                logger.LogInformation("CreateJobController receive the mes info is:{0}", JsonConvert.SerializeObject(job));

                if (!await jobRepoitory.AddAsync(job))
                    return ApiResultHelp.Error("服务器发生错误");

                eventBus.Publish(new PayloadEvent<string>("ChangeStatus"));
                return ApiResultHelp.Success("success");
            }
            catch (Exception ex)
            {
                logger.LogInformation("Create job occurs error,the error info is:{0}", ex.Message);
                return ApiResultHelp.Error("服务器发生错误");
            }


        }
        #endregion

        #region 更新


        #endregion

        //#region 取消任务

        ///// <summary>
        ///// 人工网页取消任务
        ///// </summary>
        ///// <returns></returns>
        //[HttpPut("{jobid}")]
        //public async Task<ActionResult<ApiResult>> Abort([FromServices] IOptionsMonitor<SystemParameter> options, string jobId)
        //{
        //    try
        //    {
        //        if (!await jobRepoitory.IsAnyAsync(x => x.Id == jobId))
        //        {
        //            return ApiResultHelp.Error("任务Id不存在");
        //        }

        //        var data = await jobRepoitory.FindAsync(jobId);

        //        #region 物料处理

        //        var materials = await materialRepoitory.QueryAsync();
        //        materials = materials.Where(i => i.MaterialNumber == data.Content).ToList();
        //        if (materials.Count > 0)
        //        {
        //            foreach (var item in materials)
        //            {
        //                item.IsOutStorage = false;
        //                await materialRepoitory.Context.Updateable(item).UpdateColumns(i => new { i.IsOutStorage }).ExecuteCommandAsync();
        //            }
        //        }

        //        #endregion

        //        data.UpdateTime = DateTime.Now;
        //        data.Status = TaskState.Canceled;
        //        data.Remark = "网页人工取消";
        //        await jobRepoitory.Context.Updateable(data).ExecuteCommandAsync();
        //        await jobRepoitory.Context.AsTenant().CommitTranAsync();
        //        return ApiResultHelp.Success("");
        //    }
        //    catch (Exception ex)
        //    {
        //        await jobRepoitory.Context.AsTenant().RollbackTranAsync();
        //        logger.LogError($"取消任务时发生错误，错误信息:{ex.Message}");
        //        return ApiResultHelp.Error("服务器错误");
        //    }
        //}

        //#endregion

        #region 删除

        /// <summary>
        /// 通过Id删除任务
        /// </summary>
        /// <param name="id">要删除的任务Id</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActionResult<ApiResult>> Delete(string id)
        {
            if (!await jobRepoitory.IsAnyAsync(x => x.Id == id))
            {
                return ApiResultHelp.Error("任务Id不存在");
            }
            var data = await jobRepoitory.FindAsync(id);
            if (data != null)
            {
                bool b = await jobRepoitory.DeleteByIdAsync(id);
                if (b)
                    return ApiResultHelp.Success(true);
            }
            return ApiResultHelp.Error("删除失败");
        }

        /// <summary>
        /// 批量删除任务
        /// </summary>
        /// <param name="ids">批量删除的任务Id</param>
        /// <returns></returns>
        [HttpDelete]
        public async Task<ActionResult<ApiResult>> DeleteByIds([FromBody] string[] ids)
        {


            foreach (var id in ids)
            {
                var data = await jobRepoitory.FindAsync(id);
                if (data == null)
                {
                    return ApiResultHelp.Error("can't find the job");
                }
                if (data.Status < TaskState.Complete)
                {
                    return ApiResultHelp.Error($"任务{data.Id}未完成，待任务完成或取消后可以删除该任务");
                }

                bool b = await jobRepoitory.DeleteByIdAsync(id);
                if (!b) return ApiResultHelp.Error("删除失败");
            }
            return ApiResultHelp.Success(true);
        }
        #endregion

        
        #region 查找 

        /// <summary>
        /// 分页查找任务
        /// </summary>
        /// <param name="page">分页数</param>
        /// <param name="limit">行数</param>
        /// <param name="query">筛选条件</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> GetJobByPage(int page, int limit, [FromQuery] string query)
        {
            RefAsync<int> total = 0;
            try
            {
                if (query != null)
                {
                    JObject jobject = JObject.Parse(query);
                    var models = new List<IConditionalModel>();
                    foreach (var key in jobject.Properties())
                    {
                        if (string.IsNullOrEmpty(key.Value.ToString()))
                            continue;
                        if (key.Name.ToLower() == "status")
                        {
                            models.Add(new ConditionalModel()
                            {
                                FieldName = key.Name,
                                FieldValue = key.Value.ToString(),
                                ConditionalType = ConditionalType.Equal,
                                CSharpTypeName = "int"
                            });
                        }
                        else if (key.Name.ToLower() == "type")
                        {
                            models.Add(new ConditionalModel()
                            {
                                FieldName = key.Name,
                                FieldValue = key.Value.ToString(),
                                ConditionalType = ConditionalType.Equal,
                                CSharpTypeName = "int"
                            });
                        }
                        else if (key.Name.ToLower() == "iscomplete")
                        {
                            if (key.Value.ToString() == "true")
                            {
                                models.Add(new ConditionalModel()
                                {
                                    FieldName = "Status",
                                    FieldValue = ((int)TaskState.Complete).ToString(),
                                    ConditionalType = ConditionalType.LessThan,
                                    CSharpTypeName = "int"
                                });
                            }
                        }
                        else if (key.Name.ToLower() == "istoday")
                        {
                            if (key.Value.ToString() == "true")
                            {
                                models.Add(new ConditionalModel()
                                {
                                    FieldName = "CreateTime",
                                    FieldValue = DateTime.Now.Date.ToString(),
                                    ConditionalType = ConditionalType.GreaterThanOrEqual,
                                    CSharpTypeName = "DateTime"
                                });
                            }
                        }
                        else if (key.Name.ToLower() == "createtime")
                        {
                            models.Add(new ConditionalModel()
                            {
                                FieldName = key.Name,
                                FieldValue = key.Value[0]?.ToString(),
                                ConditionalType = ConditionalType.GreaterThanOrEqual,
                                CSharpTypeName = "DateTime"
                            });
                            models.Add(new ConditionalModel()
                            {
                                FieldName = key.Name,
                                FieldValue = key.Value[1]?.ToString(),
                                ConditionalType = ConditionalType.LessThanOrEqual,
                                CSharpTypeName = "DateTime"
                            });
                        }
                        else if (key.Name.ToLower() == "updatetime")
                        {
                            models.Add(new ConditionalModel()
                            {
                                FieldName = key.Name,
                                FieldValue = key.Value[0]?.ToString(),
                                ConditionalType = ConditionalType.GreaterThanOrEqual,
                                CSharpTypeName = "DateTime"
                            });
                            models.Add(new ConditionalModel()
                            {
                                FieldName = key.Name,
                                FieldValue = key.Value[1]?.ToString(),
                                ConditionalType = ConditionalType.LessThan,
                                CSharpTypeName = "DateTime"
                            });
                        }
                        else
                        {
                            models.Add(new ConditionalModel()
                            { FieldName = key.Name, FieldValue = key.Value.ToString(), ConditionalType = ConditionalType.Like });
                        }
                    }
                    var jobs = await jobRepoitory.QueryAsync(models, page, limit, total);
                    return ApiResultHelp.Success(new { list = jobs, total = total.Value });
                }
                else
                {
                    var jobs = await jobRepoitory.QueryAsync(page, limit, total);
                    return ApiResultHelp.Success(new { list = jobs, total = total.Value });
                }
            }
            catch (Exception ex)
            {
                return ApiResultHelp.Error($"查询出错:{ex.Message}");
            }
        }


        /// <summary>
        /// 查找实时任务
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> GetRealJob(int page, int limit)
        {
            RefAsync<int> total = 0;
            try
            {
                var data = await jobRepoitory.QueryAsync(x => x.Status < TaskState.Complete, page, limit, total);
                return ApiResultHelp.Success(new { list = data, total = total.Value });
            }
            catch (Exception ex)
            {
                return ApiResultHelp.Error($"查询出错:{ex.Message}");
            }
        }

        /// <summary>
        /// 查找任务类型
        /// </summary>
        /// <returns></returns>
        [HttpGet()]
        public async Task<ApiResult> GetJobTypes()
        {
            var types = new Dictionary<string, int>();

            return await Task.Run(() =>
            {
                foreach (TaskType value in Enum.GetValues(typeof(TaskType)))
                {
                    var fi = value.GetType().GetField(value.ToString());
                    var attributes = fi?.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
                    types.Add(attributes?[0].Description, (int)value);
                }
                return ApiResultHelp.Success(types.ToArray());

            });
        }

        /// <summary>
        /// 查找任务状态
        /// </summary>
        /// <returns></returns>
        [HttpGet()]
        public async Task<ApiResult> GetJobStatus()
        {
            Dictionary<string, int> types = new();

            return await Task.Run(() =>
            {
                foreach (TaskState value in Enum.GetValues(typeof(TaskState)))
                {
                    var fi = value.GetType().GetField(value.ToString());
                    var attributes = fi?.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
                    types.Add(attributes?[0].Description, (int)value);
                }
                return ApiResultHelp.Success(types.ToArray());
            });
        }

        /// <summary>
        /// 获取当天任务信息总览
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> GetJobStatisticsInfo()
        {
            var info = await jobRepoitory.Context.Queryable<Job>().
                Where(x => SqlFunc.DateIsSame(x.CreateTime, DateTime.Now) || SqlFunc.DateIsSame(x.UpdateTime, DateTime.Now)).GroupBy(x => x.Status)
                .Select(x => new
                {
                    x.Status,
                    Count = SqlFunc.AggregateCount(x)
                })
          .ToListAsync();
            Dictionary<string, int> taskInfos = new()
            {
                ["total"] = info.Sum(x => x.Count),
                ["complete"] = info.Where(x => x.Status == TaskState.Complete).Sum(x => x.Count),
                ["error"] = info.Where(x => x.Status == TaskState.Canceled).Sum(x => x.Count),
                ["pend"] = info.Where(x => x.Status == TaskState.Pending).Sum(x => x.Count)
            };
            return ApiResultHelp.Success(taskInfos);
        }

        /// <summary>
        /// 统计任务信息
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        [HttpGet()]//DateTime start,DateTime end,string robotId
        public ApiResult QueryDate(string query)
        {
            List<DateTime> dayArray;
            JObject jobject = new JObject();
            if (query == null)
            {
                dayArray = GetAllDays(DateTime.Today.AddDays(-7), DateTime.Today).ToList();
            }
            else
            {
                jobject = JObject.Parse(query);
                var dates = jobject["updateTime"];
                if (dates != null && dates.HasValues)
                {
                    dayArray = GetAllDays(Convert.ToDateTime(dates[0]), Convert.ToDateTime(dates[1])).ToList();
                }
                else
                {
                    dayArray = GetAllDays(DateTime.Today.AddDays(-7), DateTime.Today).ToList();
                }
            }

            var db = jobRepoitory.Context;
            Console.WriteLine($"*********JOb*********{jobRepoitory.Context.GetHashCode()}***************************");
            var queryableLeft = db.Reportable(dayArray).ToQueryable<DateTime>();
            var queryableRight = db.Queryable<Job>().Where(x => SqlFunc.HasValue(x.BeginTime) && SqlFunc.HasValue(x.UpdateTime));
            var list = db.Queryable(queryableLeft, queryableRight, JoinType.Left,
                (x1, x2) => x1.ColumnName.Date == x2.CreateTime.Date)
                .GroupBy((x1, x2) => new { x1.ColumnName, x2.Type})
                .Select((x1, x2) => new
                {
                    totalTime = SqlFunc.AggregateSum(SqlFunc.DateDiff(DateType.Minute, x2.BeginTime.Value, x2.UpdateTime.Value)),
                    Type = SqlFunc.ToString(x2.Type),
                    count = SqlFunc.AggregateCount(x1),
                    day = x1.ColumnName.Date
                }).ToList();
            //  var da = DateTime.Now.TimeOfDay.TotalSeconds;
            var datas = list.Where(x => x != null).GroupBy(x => new { x.day }).Select(g => new
            {
                TaskCount = g.Sum(x => x.count),
                Day = g.Key.day,
                Efficiency = Math.Round(g.Where(x => x.Type != "9" && x.Type != "10").Sum(x => x.totalTime) / (g.Key.day == DateTime.Today ? DateTime.Now.TimeOfDay.TotalMinutes * 1.0 : 24 * 60 * 1.0), 2)

            }).ToList();
            return ApiResultHelp.Success(new { list = datas, total = datas.Count });
        }


        /// <summary>
        /// 获取固定日期范围内的所有日期，以数组形式返回
        /// </summary>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        private DateTime[] GetAllDays(DateTime startTime, DateTime endTime)
        {
            var listDay = new List<DateTime>();
            var dtDay = new DateTime();
            //循环比较，取出日期；
            for (dtDay = startTime; dtDay.CompareTo(endTime) <= 0; dtDay = dtDay.AddDays(1))
            {
                listDay.Add(dtDay);
            }
            return listDay.ToArray();
        }

        #endregion
    }
}
